//////////////////////////////////////////////
//	File:		CDXCamera.cpp
//	Aurthor:	Sebastian Lewicki
//	Purpose:	Camera class included in the DirectX enigine
/////////////////////////////////////////////

#include "CDXCamera.h"

////////////////////////////////////////////////////////////
//	Function:	CDXCamera
//	Purpose:	Constructor
//	In:			Flag to choose between left or right handed coordinates
////////////////////////////////////////////////////////////
CDXCamera::CDXCamera(bool bRightHanded)
{
	// Initialize the camera
	memset(&m_Matrix, 0, sizeof(D3DXMATRIX));
	memset(&m_Projection, 0, sizeof(D3DXMATRIX));

	m_Up = D3DXVECTOR3(0.0f, 1.0f, 0.0f);
	m_Forward = (bRightHanded) ? D3DXVECTOR3(0.0f, 0.0f, 1.0f) : D3DXVECTOR3(0.0f, 0.0f, -1.0f);
	
	m_Buffer.empty();
}

////////////////////////////////////////////////////////////
//	Function:	CDXCamera
//	Purpose:	Constructor
//	In:			A vector of 3 floats for the position
//	In:			Flag to choose between left or right handed coordinates
////////////////////////////////////////////////////////////
CDXCamera::CDXCamera(D3DXVECTOR3 fPos, bool bRightHanded)
{
	// Initialize the camera
	memset(&m_Matrix, 0, sizeof(D3DXMATRIX));
	memset(&m_Projection, 0, sizeof(D3DXMATRIX));

	m_Up = D3DXVECTOR3(0.0f, 1.0f, 0.0f);
	m_Forward = (bRightHanded) ? D3DXVECTOR3(0.0f, 0.0f, 1.0f) : D3DXVECTOR3(0.0f, 0.0f, -1.0f);

	m_Buffer.empty();

	// Set the Matrix position
	m_Matrix._41 = fPos.x;
	m_Matrix._42 = fPos.y;
	m_Matrix._43 = fPos.z;

	m_Buffer.push(m_Matrix);
}

////////////////////////////////////////////////////////////
//	Function:	CDXCamera
//	Purpose:	Constructor
//	In:			Position on the X-Axis
//	In:			Position on the Y-Axis
//	In:			Position on the Z-Axis
//	In:			Flag to choose between left or right handed coordinates
////////////////////////////////////////////////////////////
CDXCamera::CDXCamera(float fX, float fY, float fZ, bool bRightHanded)
{
	// Initialize the camera
	memset(&m_Matrix, 0, sizeof(D3DXMATRIX));
	memset(&m_Projection, 0, sizeof(D3DXMATRIX));

	m_Up = D3DXVECTOR3(0.0f, 1.0f, 0.0f);
	m_Forward = (bRightHanded) ? D3DXVECTOR3(0.0f, 0.0f, 1.0f) : D3DXVECTOR3(0.0f, 0.0f, -1.0f);

	m_Buffer.empty();

	// Set the Matrix position
	m_Matrix._41 = fX;
	m_Matrix._42 = fY;
	m_Matrix._43 = fZ;

	m_Buffer.push(m_Matrix);
}

////////////////////////////////////////////////////////////
//	Function:	~CDXCamera
//	Purpose:	Destructor
////////////////////////////////////////////////////////////
CDXCamera::~CDXCamera()
{
}

////////////////////////////////////////////////////////////
//	Function:	CreateProjMatrixLH
//	Purpose:	Creates the projection matrix from the field of view using left handed coordinate system
//	In:			Float variable for the field of view, in radians.
//	In:			Aspect ratio, defined as view space width divided by height.
//	In:			Float variable for the near plane.
//	In:			Float variable for the far plane.
//	Out:		Returns a set projection matrix
////////////////////////////////////////////////////////////
D3DXMATRIX	CDXCamera::CreateProjMatrixLH(float fFoV, float fAspect, float fNear, float fFar)
{
	D3DXMatrixPerspectiveFovLH(&m_Projection, fFoV, fAspect, fNear, fFar);
	return m_Projection;
}

////////////////////////////////////////////////////////////
//	Function:	CreateProjMatrix
//	Purpose:	Creates the projection matrix from the field of view
//	In:			Float variable for the field of view, in radians.
//	In:			Aspect ratio, defined as view space width divided by height.
//	In:			Float variable for the near plane.
//	In:			Float variable for the far plane.
//	Out:		Returns a set projection matrix
////////////////////////////////////////////////////////////
D3DXMATRIX	CDXCamera::CreateProjMatrix(float fFoV, float fAspect, float fNear, float fFar)
{
	D3DXMatrixPerspectiveFovRH(&m_Projection, fFoV, fAspect, fNear, fFar);
	return m_Projection;
}

////////////////////////////////////////////////////////////
//	Function:	LookAtLH
//	Purpose:	Modifies the camera matrix to look at a target
//	In:			the target's position
//	Out:		Returns the new camera matrix
////////////////////////////////////////////////////////////
D3DXMATRIX	CDXCamera::LookAtLH(D3DXVECTOR3* fTargetPosition)
{
	D3DXVECTOR3 fPosition = D3DXVECTOR3(m_Matrix._41, m_Matrix._42, m_Matrix._43);
	D3DXMatrixLookAtLH(&m_Matrix, &fPosition, fTargetPosition, &m_Up);
	return m_Matrix;
}

////////////////////////////////////////////////////////////
//	Function:	LookAtLH
//	Purpose:	Modifies the camera matrix to look at a target
//	In:			the target's position on the X-Axis
//	In:			the target's position on the Y-Axis
//	In:			the target's position on the Z-Axis
//	Out:		Returns the new camera matrix
////////////////////////////////////////////////////////////
D3DXMATRIX	CDXCamera::LookAtLH(float fTargetXPositionX, float fTargetPositionY, float fTargetPositionZ)
{
	D3DXVECTOR3 fPosition = D3DXVECTOR3(m_Matrix._41, m_Matrix._42, m_Matrix._43);
	D3DXVECTOR3 fTargetPosition = D3DXVECTOR3(fTargetXPositionX, fTargetPositionY, fTargetPositionZ);
	D3DXMatrixLookAtLH(&m_Matrix, &fPosition, &fTargetPosition, &m_Up);
	return m_Matrix;
}

////////////////////////////////////////////////////////////
//	Function:	LookAt
//	Purpose:	Modifies the camera matrix to look at a target
//	In:			the target's position
//	Out:		Returns the new camera matrix
////////////////////////////////////////////////////////////
D3DXMATRIX	CDXCamera::LookAt(D3DXVECTOR3* fTargetPosition)
{
	D3DXVECTOR3 fPosition = D3DXVECTOR3(m_Matrix._41, m_Matrix._42, m_Matrix._43);
	D3DXMatrixLookAtRH(&m_Matrix, &fPosition, fTargetPosition, &m_Up);
	return m_Matrix;
}

////////////////////////////////////////////////////////////
//	Function:	LookAt
//	Purpose:	Modifies the camera matrix to look at a target
//	In:			the target's position on the X-Axis
//	In:			the target's position on the Y-Axis
//	In:			the target's position on the Z-Axis
//	Out:		Returns the new camera matrix
////////////////////////////////////////////////////////////
D3DXMATRIX	CDXCamera::LookAt(float fTargetXPositionX, float fTargetPositionY, float fTargetPositionZ)
{
	D3DXVECTOR3 fPosition = D3DXVECTOR3(m_Matrix._41, m_Matrix._42, m_Matrix._43);
	D3DXVECTOR3 fTargetPosition = D3DXVECTOR3(fTargetXPositionX, fTargetPositionY, fTargetPositionZ);
	D3DXMatrixLookAtRH(&m_Matrix, &fPosition, &fTargetPosition, &m_Up);
	return m_Matrix;
}

////////////////////////////////////////////////////////////
//	Function:	SoftAttachLH
//	Purpose:	Modifies the camera matrix to follow the target with a time delay (left handed)
//	In:			Matrix of the target
//	In:			Vector to offset by
//	Out:		Returns the new camera matrix
////////////////////////////////////////////////////////////
D3DXMATRIX	CDXCamera::SoftAttachLH(D3DXMATRIX& Target, D3DXVECTOR3& Offset)
{
	D3DXVECTOR3 fPosition = D3DXVECTOR3(m_Matrix._41, m_Matrix._42, m_Matrix._43);
	D3DXVECTOR3 fTargetPosition = D3DXVECTOR3(Target._41, Target._42, Target._43);
	m_Buffer.push(Target);
	m_Matrix = m_Buffer.front();
	D3DXMatrixTranslation(&m_Matrix, Offset.x, Offset.y, Offset.z);
	D3DXMatrixLookAtLH(&m_Matrix, &fPosition, &fTargetPosition, &m_Up);
	m_Buffer.pop();
	return m_Matrix;
}

////////////////////////////////////////////////////////////
//	Function:	SoftAttach
//	Purpose:	Modifies the camera matrix to follow the target with a time delay
//	In:			Matrix of the target
//	In:			Vector to offset by
//	Out:		Returns the new camera matrix
////////////////////////////////////////////////////////////
D3DXMATRIX	CDXCamera::SoftAttach(D3DXMATRIX& Target, D3DXVECTOR3& Offset)
{
	D3DXVECTOR3 fPosition = D3DXVECTOR3(m_Matrix._41, m_Matrix._42, m_Matrix._43);
	D3DXVECTOR3 fTargetPosition = D3DXVECTOR3(Target._41, Target._42, Target._43);
	m_Buffer.push(Target);
	m_Matrix = m_Buffer.front();
	D3DXMatrixTranslation(&m_Matrix, Offset.x, Offset.y, Offset.z);
	D3DXMatrixLookAtRH(&m_Matrix, &fPosition, &fTargetPosition, &m_Up);
	m_Buffer.pop();
	return m_Matrix;
}

////////////////////////////////////////////////////////////
//	Function:	SetPosition
//	Purpose:	Sets the cameras position
//	In:			Position vector
////////////////////////////////////////////////////////////
void	CDXCamera::SetPosition(D3DXVECTOR3 fPosition)
{
	m_Matrix._41 = fPosition.x;
	m_Matrix._42 = fPosition.y;
	m_Matrix._43 = fPosition.z;
}

////////////////////////////////////////////////////////////
//	Function:	SetPosition
//	Purpose:	Sets the cameras position
//	In:			Position along the X-Axis
//	In:			Position along the Y-Axis
//	In:			Position along the Z-Axis
////////////////////////////////////////////////////////////
void	CDXCamera::SetPosition(float fPosX, float fPosY, float fPosZ)
{
	m_Matrix._41 = fPosX;
	m_Matrix._42 = fPosY;
	m_Matrix._43 = fPosZ;
}